﻿using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Xml.Serialization;
using EnvDTE;

using Basic.DataEntities;
using Basic.Designer;
using Basic.Enums;
using Basic.Interfaces;
using System.Linq.Expressions;
using Basic.EntityLayer;
using Basic.DataAccess;

namespace Basic.Configuration
{
	/// <summary>
	/// 表示抽象配置命令
	/// </summary>
	[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
	public abstract class DataCommandElement : AbstractCommandElement, IXmlSerializable
	{
		protected internal const string CShartFileExtension = "cs";
		protected internal const string VisualBasicFileExtension = "vb";
		private readonly DataEntityElement _EntityElement;
		private readonly PersistentConfiguration _Persistent;
		/// <summary>
		/// 初始化 StaticCommandElement 类实例
		/// </summary>
		protected DataCommandElement(DataEntityElement entity)
			: base(entity)
		{
			_EntityElement = entity; _Persistent = entity.Persistent;
		}

		/// <summary>
		/// 获取命令所关联的方法名称
		/// </summary>
		[System.ComponentModel.Description("获取或设置命令名称"), System.ComponentModel.DefaultValue("")]
		[Basic.Designer.PersistentCategory(PersistentCategoryAttribute.CategoryCodeGenerator)]
		[System.ComponentModel.Browsable(false)]
		public abstract string MethodName { get; }

		/// <summary>
		/// 表示 Run 属性
		/// </summary>
		protected internal const string ExecutableAttribute = "Executable";

		/// <summary>
		/// 表示 Modifier 属性
		/// </summary>
		protected internal const string ModifierAttribute = "Modifier";

		/// <summary>
		/// 表示 Kind 属性
		/// </summary>
		protected internal const string KindAttribute = "Kind";
		/// <summary>
		/// 表示 Comment 元素标签
		/// </summary>
		protected internal const string CommentAttribute = "Comment";

		/// <summary>
		/// 当前实体模型。
		/// </summary>
		protected internal DataEntityElement EntityElement { get { return _EntityElement; } }

		/// <summary>
		/// 当前实体模型。
		/// </summary>
		protected internal PersistentConfiguration Persistent { get { return _Persistent; } }

		private MethodModifierEnum _MethodModifier = MethodModifierEnum.Public;
		/// <summary>
		/// 当前方法的修饰符。
		/// </summary>
		[System.ComponentModel.Description("方法的修饰符")]
		[Basic.Designer.PersistentDisplay("DisplayName_Modifier")]
		[System.ComponentModel.DefaultValue(typeof(MethodModifierEnum), "Public")]
		[PersistentCategoryAttribute(PersistentCategoryAttribute.CategoryCodeGenerator)]
		public MethodModifierEnum Modifier
		{
			get { return _MethodModifier; }
			set
			{
				if (_MethodModifier != value)
				{
					_MethodModifier = value;
					base.RaisePropertyChanged("Modifier");
				}
			}
		}

		private ConfigurationTypeEnum _ConfigurationKind = ConfigurationTypeEnum.Other;
		/// <summary>
		/// 获取或设置数据命令类型。
		/// </summary>
		[System.ComponentModel.Description("数据命令类型")]
		[Basic.Designer.PersistentDisplay("DisplayName_ConfigurationKind")]
		[System.ComponentModel.DefaultValue(typeof(ConfigurationTypeEnum), "Other")]
		[PersistentCategoryAttribute(PersistentCategoryAttribute.CategoryCodeGenerator)]
		public ConfigurationTypeEnum Kind
		{
			get { return _ConfigurationKind; }
			set
			{
				if (_ConfigurationKind != value)
				{
					_ConfigurationKind = value;
					if (_ConfigurationKind == ConfigurationTypeEnum.AddNew) { base.Name = AbstractDbAccess.CreateName; }
					else if (_ConfigurationKind == ConfigurationTypeEnum.Modify) { base.Name = AbstractDbAccess.ModifyName; }
					else if (_ConfigurationKind == ConfigurationTypeEnum.Remove) { base.Name = AbstractDbAccess.RemoveName; }
					else if (_ConfigurationKind == ConfigurationTypeEnum.SearchTable) { base.Name = AbstractDbAccess.SearchTableName; }
					base.RaisePropertyChanged("Kind");
					base.RaisePropertyChanged("Name");
					base.RaisePropertyChanged("ConfigurationName");
				}
			}
		}

		private string _Comment = string.Empty;
		/// <summary>
		/// 获取或设置命令描述
		/// </summary>
		[System.ComponentModel.Description("获取或设置命令描述")]
		[System.ComponentModel.DefaultValue("")]
		[PersistentCategoryAttribute(PersistentCategoryAttribute.CategoryCodeGenerator)]
		public string Comment
		{
			get { return _Comment; }
			set
			{
				if (_Comment != value)
				{
					base.OnPropertyChanging("Comment");
					_Comment = value;
					base.RaisePropertyChanged("Comment");
				}
			}
		}

		/// <summary>
		/// 表示 AutoGenerated 属性
		/// </summary>
		protected internal const string AutoGeneratedAttribute = "Auto";
		private bool _AutoGenerated = true;
		/// <summary>
		/// 获取或设置一个布尔类型的值，该值指示当前命令是否以实体类作为参数传入。
		/// </summary>
		[System.ComponentModel.Description("获取或设置一个布尔类型的值，该值指示当前命令是否自动生成方法以供调用。")]
		[System.ComponentModel.DefaultValue(true)]
		[Basic.Designer.PersistentDisplay("DisplayName_AutoGenerated")]
		[PersistentCategoryAttribute(PersistentCategoryAttribute.CategoryCodeGenerator)]
		public bool AutoGenerated
		{
			get { return _AutoGenerated; }
			set
			{
				if (_AutoGenerated != value)
				{
					base.OnPropertyChanging("AutoGenerated");
					_AutoGenerated = value;
					base.RaisePropertyChanged("AutoGenerated");
				}
			}
		}

		/// <summary>
		/// 表示 AsyncGenerated 属性
		/// </summary>
		protected internal const string AsyncGeneratedAttribute = "Async";
		private bool _AsyncGenerated = false;
		/// <summary>
		/// 获取或设置一个布尔类型的值，该值指示当前命令是否以实体类作为参数传入。
		/// </summary>
		[System.ComponentModel.Description("获取或设置一个布尔类型的值，该值指示当前命令是否自动生成方法以供调用。")]
		[System.ComponentModel.DefaultValue(false)]
		[Basic.Designer.PersistentDisplay("DisplayName_AsyncGenerated")]
		[PersistentCategoryAttribute(PersistentCategoryAttribute.CategoryCodeGenerator)]
		public bool AsyncGenerated
		{
			get { return _AsyncGenerated; }
			set
			{
				if (_AsyncGenerated != value)
				{
					_AsyncGenerated = value;
					base.RaisePropertyChanged("AsyncGenerated");
				}
			}
		}

		/// <summary>
		/// 从对象的 XML 表示形式读取属性。
		/// </summary>
		/// <param name="name">属性名称。</param>
		/// <param name="value">属性值</param>
		/// <returns>如果属性存在读取成功则返回true，否则返回false，有子类读取。</returns>
		protected internal override bool ReadAttribute(string name, string value)
		{
			if (name == ModifierAttribute) { return Enum.TryParse<MethodModifierEnum>(value, true, out _MethodModifier); }
			else if (name == KindAttribute && value == "AddNew") { _ConfigurationKind = ConfigurationTypeEnum.AddNew; return true; }
			else if (name == KindAttribute) { return Enum.TryParse<ConfigurationTypeEnum>(value, true, out _ConfigurationKind); }
			else if (name == AutoGeneratedAttribute) { _AutoGenerated = Convert.ToBoolean(value); return true; }
			else if (name == AsyncGeneratedAttribute) { _AsyncGenerated = Convert.ToBoolean(value); return true; }
			else if (name == CommentAttribute) { Comment = value; return true; }
			return base.ReadAttribute(name, value);
		}

		/// <summary>
		/// 从对象的 XML 表示形式生成该对象扩展信息。
		/// </summary>
		/// <param name="reader">对象从中进行反序列化的 XmlReader 流。</param>
		/// <returns>判断当前对象是否已经读取完成，如果读取完成则返回true，否则返回false。</returns>
		internal protected override bool ReadContent(System.Xml.XmlReader reader)
		{
			return base.ReadContent(reader);
		}

		/// <summary>
		/// 将对象转换为其 XML 表示形式中属性部分。
		/// </summary>
		/// <param name="writer">对象要序列化为的 XmlWriter 流。</param>
		/// <returns>如果属性存在读取成功则返回true，否则返回false，有子类读取。</returns>
		protected internal override void WriteAttribute(System.Xml.XmlWriter writer)
		{
			base.WriteAttribute(writer);
			if (_MethodModifier != MethodModifierEnum.Public)
				writer.WriteAttributeString(ModifierAttribute, _MethodModifier.ToString());
			if (_ConfigurationKind != ConfigurationTypeEnum.Other)
				writer.WriteAttributeString(KindAttribute, _ConfigurationKind.ToString());
			if (!_AutoGenerated)
				writer.WriteAttributeString(AutoGeneratedAttribute, _AutoGenerated.ToString().ToLower());
			if (_AsyncGenerated)
				writer.WriteAttributeString(AsyncGeneratedAttribute, _AsyncGenerated.ToString().ToLower());
			if (!string.IsNullOrWhiteSpace(_Comment))
				writer.WriteAttributeString(CommentAttribute, _Comment);
		}

		/// <summary>
		/// 将对象转换为其 XML 表示形式。
		/// </summary>
		/// <param name="writer">对象要序列化为的 XmlWriter 流。</param>
		protected internal override void WriteContent(System.Xml.XmlWriter writer)
		{
			//if (ExecutMethod == CommandMethodEnum.FillDataSet)
			//   dataConditionElement.WriteXml(writer);
			//else if (ExecutMethod == CommandMethodEnum.FillDataTable)
			//   dataConditionElement.WriteXml(writer);
			//else if (ExecutMethod == CommandMethodEnum.GetPagination)
			//   dataConditionElement.WriteXml(writer);
			//else if (ExecutMethod == CommandMethodEnum.GetDataTable)
			//   dataConditionElement.WriteXml(writer);
			//else if (ExecutMethod == CommandMethodEnum.GetEntities)
			//   dataConditionElement.WriteXml(writer);
			base.WriteContent(writer);
		}

		#region 生成Fill（DataSet）方法
		/// <summary>
		/// 
		/// </summary>
		/// <param name="members"></param>
		/// <param name="method"></param>
		protected internal void GenerateContextDataSet(CodeTypeMemberCollection members, CodeMemberMethod method)
		{
			string paramTable = string.Format("<param name=\"dataSet\">表示 {0} 类的实例。</param>", _EntityElement.DataTableName);
			string paramComment = string.Format("<param name=\"condition\">表示 {0} 类的实例。</param>", _EntityElement.Condition.EntityName);
			string returnComment = string.Format("<returns>返回查询结果，此结果表示 {0} 类的集合。</returns>", _EntityElement.EntityName);
			method.Comments.Add(new CodeCommentStatement(paramTable, true));
			method.Comments.Add(new CodeCommentStatement(paramComment, true));
			method.Comments.Add(new CodeCommentStatement(returnComment, true));
			method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(DataSet), "dataSet"));
			method.Parameters.Add(new CodeParameterDeclarationExpression(_EntityElement.Condition.EntityName, "condition"));
			CodeVariableReferenceExpression dsReference = new CodeVariableReferenceExpression("dataSet");
			CodeVariableReferenceExpression conditionReference = new CodeVariableReferenceExpression("condition");
			CodeVariableReferenceExpression accessReference = new CodeVariableReferenceExpression("access");
			CodeMethodReferenceExpression methodReference = new CodeMethodReferenceExpression(accessReference, MethodName);
			CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(methodReference);
			methodInvoke.Parameters.Add(dsReference);
			methodInvoke.Parameters.Add(conditionReference);
			CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement(methodInvoke);
			method.ReturnType = new CodeTypeReference(typeof(int));
			method.Statements.Add(returnStatement);
		}

		protected internal void GenerateDesignerDataSet(CodeTypeMemberCollection members)
		{
			CodeMemberMethod method = new CodeMemberMethod(); members.Add(method);
			this.CreateDesignerMemberMethod(method);
			string paramTable = string.Format("<param name=\"table\">表示 DataTable 类的实例。</param>");
			string paramComment = string.Format("<param name=\"condition\">表示 {0} 类的实例。</param>", _EntityElement.Condition.EntityName);
			string returnComment = string.Format("<returns>返回查询结果，此结果表示 {0} 类的集合。</returns>", _EntityElement.EntityName);
			method.Comments.Add(new CodeCommentStatement(paramTable, true));
			method.Comments.Add(new CodeCommentStatement(paramComment, true));
			method.Comments.Add(new CodeCommentStatement(returnComment, true));

			CodeTypeReference codeTypeReference = new CodeTypeReference(_EntityElement.Condition.EntityName);
			method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(DataSet), "dataSet"));
			method.Parameters.Add(new CodeParameterDeclarationExpression(codeTypeReference, "condition"));

			CodeMethodInvokeExpression codeMethodInvoke = new CodeMethodInvokeExpression(new CodeBaseReferenceExpression(), "Fill");
			codeMethodInvoke.Parameters.Add(new CodeFieldReferenceExpression(null, "dataSet"));
			codeMethodInvoke.Parameters.Add(new CodePrimitiveExpression(this.ConfigurationName));
			codeMethodInvoke.Parameters.Add(new CodeFieldReferenceExpression(null, "condition"));
			method.ReturnType = new CodeTypeReference(typeof(int));
			method.Statements.Add(codeMethodInvoke);
		}
		#endregion

		#region 生成Fill（DataTable）方法
		/// <summary>
		/// 
		/// </summary>
		/// <param name="members"></param>
		/// <param name="method"></param>
		protected internal void GenerateContextDataTable(CodeTypeMemberCollection members, CodeMemberMethod method)
		{
			string paramTable = string.Format("<param name=\"table\">表示 DataTable 类的实例。</param>");
			string paramComment = string.Format("<param name=\"condition\">表示 {0} 类的实例。</param>", _EntityElement.Condition.EntityName);
			string returnComment = string.Format("<returns>返回查询结果，此结果表示 {0} 类的集合。</returns>", _EntityElement.EntityName);
			method.Comments.Add(new CodeCommentStatement(paramTable, true));
			method.Comments.Add(new CodeCommentStatement(paramComment, true));
			method.Comments.Add(new CodeCommentStatement(returnComment, true));
			method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(DataTable), "table"));
			method.Parameters.Add(new CodeParameterDeclarationExpression(_EntityElement.Condition.EntityName, "condition"));
			CodeVariableReferenceExpression dsReference = new CodeVariableReferenceExpression("table");
			CodeVariableReferenceExpression conditionReference = new CodeVariableReferenceExpression("condition");
			CodeVariableReferenceExpression accessReference = new CodeVariableReferenceExpression("access");
			CodeMethodReferenceExpression methodReference = new CodeMethodReferenceExpression(accessReference, MethodName);
			CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(methodReference);
			methodInvoke.Parameters.Add(dsReference);
			methodInvoke.Parameters.Add(conditionReference);
			CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement(methodInvoke);
			method.ReturnType = new CodeTypeReference(typeof(int));
			method.Statements.Add(returnStatement);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="members"></param>
		protected internal void GenerateDesignerDataTable(CodeTypeMemberCollection members)
		{
			CodeMemberMethod method = new CodeMemberMethod(); members.Add(method);
			this.CreateDesignerMemberMethod(method);
			string paramTable = string.Format("<param name=\"table\">表示 DataTable 类的实例。</param>");
			string paramComment = string.Format("<param name=\"condition\">表示 {0} 类的实例。</param>", _EntityElement.Condition.EntityName);
			string returnComment = string.Format("<returns>返回查询结果，此结果表示 {0} 类的集合。</returns>", _EntityElement.EntityName);
			method.Comments.Add(new CodeCommentStatement(paramTable, true));
			method.Comments.Add(new CodeCommentStatement(paramComment, true));
			method.Comments.Add(new CodeCommentStatement(returnComment, true));
			method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(DataTable), "table"));
			method.Parameters.Add(new CodeParameterDeclarationExpression(_EntityElement.Condition.EntityName, "condition"));
			CodeVariableReferenceExpression dsReference = new CodeVariableReferenceExpression("table");
			CodeVariableReferenceExpression conditionReference = new CodeVariableReferenceExpression("condition");
			CodeMethodReferenceExpression methodReference = new CodeMethodReferenceExpression(new CodeBaseReferenceExpression(), "Fill");
			CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(methodReference);
			methodInvoke.Parameters.Add(dsReference);
			methodInvoke.Parameters.Add(new CodePrimitiveExpression(this.ConfigurationName));
			methodInvoke.Parameters.Add(conditionReference);
			method.ReturnType = new CodeTypeReference(typeof(int));
			method.Statements.Add(new CodeMethodReturnStatement(methodInvoke));
		}
		#endregion

		#region 生成 GetPagination 方法
		/// <summary>
		/// 
		/// </summary>
		/// <param name="members"></param>
		/// <param name="method"></param>
		protected internal void GenerateContextGetPagination(CodeTypeMemberCollection members, CodeMemberMethod method)
		{
			string paramComment = string.Format("<param name=\"condition\">表示 {0} 类的实例。</param>", _EntityElement.Condition.EntityName);
			string returnComment = string.Format("<returns>返回查询结果，此结果表示 {0} 类的集合。</returns>", _EntityElement.EntityName);
			method.Comments.Add(new CodeCommentStatement(paramComment, true));
			method.Comments.Add(new CodeCommentStatement(returnComment, true));
			if (_EntityElement.Condition.Arguments.Count > 0)
				method.Parameters.Add(new CodeParameterDeclarationExpression(_EntityElement.Condition.EntityName, "condition"));
			else if (_EntityElement.Condition.BaseClass != typeof(AbstractCondition).FullName)
				method.Parameters.Add(new CodeParameterDeclarationExpression(_EntityElement.Condition.EntityName, "condition"));

			CodeVariableReferenceExpression conditionReference = new CodeVariableReferenceExpression("condition");
			CodeVariableReferenceExpression accessReference = new CodeVariableReferenceExpression("access");
			CodeMethodReferenceExpression methodReference = new CodeMethodReferenceExpression(accessReference, MethodName);
			//methodReference.TypeArguments.Add(entity.ClassName);
			CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(methodReference);
			if (_EntityElement.Condition.Arguments.Count > 0)
				methodInvoke.Parameters.Add(conditionReference);
			else if (_EntityElement.Condition.BaseClass != typeof(AbstractCondition).FullName)
				methodInvoke.Parameters.Add(conditionReference);
			CodeMethodReturnStatement codeResult = new CodeMethodReturnStatement(methodInvoke);
			method.ReturnType = new CodeTypeReference(typeof(IPagination).Name);
			method.ReturnType.TypeArguments.Add(_EntityElement.EntityName);
			method.Statements.Add(codeResult);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="members"></param>
		protected internal void GenerateDesignerGetPagination(CodeTypeMemberCollection members)
		{
			CodeMemberMethod method = new CodeMemberMethod(); members.Add(method);
			this.CreateDesignerMemberMethod(method);
			string paramComment = string.Format("<param name=\"condition\">表示 {0} 类的实例。</param>", _EntityElement.Condition.EntityName);
			string returnComment = string.Format("<returns>返回查询结果，此结果表示 {0} 类的集合。</returns>", _EntityElement.EntityName);
			method.Comments.Add(new CodeCommentStatement(paramComment, true));
			method.Comments.Add(new CodeCommentStatement(returnComment, true));

			if (_EntityElement.Condition.Arguments.Count > 0)
				method.Parameters.Add(new CodeParameterDeclarationExpression(_EntityElement.Condition.EntityName, "condition"));
			else if (_EntityElement.Condition.BaseClass != typeof(AbstractCondition).FullName)
				method.Parameters.Add(new CodeParameterDeclarationExpression(_EntityElement.Condition.EntityName, "condition"));

			CodeVariableReferenceExpression conditionReference = new CodeVariableReferenceExpression("condition");
			CodeMethodReferenceExpression methodReference = new CodeMethodReferenceExpression(new CodeBaseReferenceExpression(), "GetPagination");
			methodReference.TypeArguments.Add(_EntityElement.EntityName);
			CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(methodReference);
			methodInvoke.Parameters.Add(new CodePrimitiveExpression(this.ConfigurationName));
			if (_EntityElement.Condition.Arguments.Count > 0)
				methodInvoke.Parameters.Add(conditionReference);
			else if (_EntityElement.Condition.BaseClass != typeof(AbstractCondition).FullName)
				methodInvoke.Parameters.Add(conditionReference);


			method.ReturnType = new CodeTypeReference(typeof(IPagination).Name);
			method.ReturnType.TypeArguments.Add(_EntityElement.EntityName);
			method.Statements.Add(new CodeMethodReturnStatement(methodInvoke));
		}
		#endregion

		#region 生成 ExecuteCore<DataRow> 方法
		/// <summary>
		/// 生成 ExecuteCore 代码段
		/// </summary>
		/// <param name="members">表示CodeDOM方法集合</param>
		/// <param name="method">表示CodeDOM方法</param>
		protected virtual void GenerateContextExecuteCore(CodeTypeMemberCollection members, CodeMemberMethod method) { }

		/// <summary>
		/// 生成 ExecuteCore 代码段
		/// </summary>
		/// <param name="members">表示CodeDOM方法集合</param>
		protected virtual void GenerateDesignerExecuteCore(CodeTypeMemberCollection members) { }
		#endregion

		#region 生成 ExecuteNonQuery 方法
		/// <summary>
		/// 生成 ExecuteNonQuery 方法调用
		/// </summary>
		/// <param name="members">方法集合</param>
		/// <param name="method">当前方法主体</param>
		protected virtual void GenerateContextExecuteNonQuery(CodeTypeMemberCollection members, CodeMemberMethod method) { }

		/// <summary>
		/// 生成 ExecuteNonQuery 方法调用
		/// </summary>
		/// <param name="members">方法集合</param>
		/// <param name="method">当前方法主体</param>
		/// <param name="targetFramework">生成代码的目标框架版本（例如：262144=v4.0）</param>
		protected virtual void GenerateDesignerExecuteNonQuery(CodeTypeMemberCollection members, int targetFramework) { }
		#endregion

		#region 生成 ExecuteReader 方法
		protected internal void GenerateContextExecuteReader(CodeTypeMemberCollection members, CodeMemberMethod method)
		{
			string paramComment = string.Format("<param name=\"entity\">表示 {0} 类的实例。</param>", _EntityElement.EntityName);
			string returnComment = string.Format("<returns>执行ransact-SQL语句的返回值。</returns>");
			method.Comments.Add(new CodeCommentStatement(paramComment, true));
			method.Comments.Add(new CodeCommentStatement(returnComment, true));
			method.Parameters.Add(new CodeParameterDeclarationExpression(_EntityElement.EntityName, "entity"));
			CodeVariableReferenceExpression entityReference = new CodeVariableReferenceExpression("entity");
			CodeVariableReferenceExpression accessReference = new CodeVariableReferenceExpression("access");
			CodeMethodReferenceExpression methodReference = new CodeMethodReferenceExpression(accessReference, MethodName);
			CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(methodReference);
			methodInvoke.Parameters.Add(entityReference);
			CodeMethodReturnStatement codeResult = new CodeMethodReturnStatement(methodInvoke);
			method.ReturnType = new CodeTypeReference(typeof(DbDataReader).Name);
			method.Statements.Add(codeResult);
		}

		protected internal void GenerateDesignerExecuteReader(CodeTypeMemberCollection members)
		{
			CodeMemberMethod method = new CodeMemberMethod(); members.Add(method);
			this.CreateDesignerMemberMethod(method);
			string paramComment = string.Format("<param name=\"entity\">表示 {0} 类的实例。</param>", _EntityElement.EntityName);
			string returnComment = string.Format("<returns>执行ransact-SQL语句的返回值。</returns>");
			method.Comments.Add(new CodeCommentStatement(paramComment, true));
			method.Comments.Add(new CodeCommentStatement(returnComment, true));
			CodeMethodReferenceExpression methodReference = new CodeMethodReferenceExpression();
			methodReference.MethodName = "ExecuteReader";
			methodReference.TargetObject = new CodeBaseReferenceExpression();
			CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(methodReference);
			methodInvoke.Parameters.Add(new CodePrimitiveExpression(this.ConfigurationName));
			if (this.Parameters.Count > 0)
			{
				method.Parameters.Add(new CodeParameterDeclarationExpression(_EntityElement.EntityName, "entity"));
				method.Comments.Add(new CodeCommentStatement(paramComment, true));
				methodInvoke.Parameters.Add(new CodeVariableReferenceExpression("entity"));
			}
			CodeMethodReturnStatement codeResult = new CodeMethodReturnStatement(methodInvoke);
			method.ReturnType = new CodeTypeReference(typeof(DbDataReader).Name);
			method.Statements.Add(codeResult);
		}
		#endregion

		#region 生成 ExecuteScalar 方法
		/// <summary>
		/// 生成 ExecuteScalar 方法调用
		/// </summary>
		/// <param name="members">方法集合</param>
		/// <param name="method">当前方法主体</param>
		protected virtual void GenerateContextExecuteScalar(CodeTypeMemberCollection members, CodeMemberMethod method)
		{
			string paramComment = string.Format("<param name=\"entity\">表示 {0} 类的实例。</param>", _EntityElement.EntityName);
			string returnComment = string.Format("<returns>执行ransact-SQL语句的返回值。</returns>");
			method.Comments.Add(new CodeCommentStatement(paramComment, true));
			method.Comments.Add(new CodeCommentStatement(returnComment, true));
			method.Parameters.Add(new CodeParameterDeclarationExpression(_EntityElement.EntityName, "entity"));
			CodeVariableReferenceExpression entityReference = new CodeVariableReferenceExpression("entity");
			CodeVariableReferenceExpression accessReference = new CodeVariableReferenceExpression("access");
			CodeMethodReferenceExpression methodReference = new CodeMethodReferenceExpression(accessReference, MethodName);
			CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(methodReference);
			methodInvoke.Parameters.Add(entityReference);
			CodeMethodReturnStatement codeResult = new CodeMethodReturnStatement(methodInvoke);
			method.ReturnType = new CodeTypeReference(typeof(object), CodeTypeReferenceOptions.GenericTypeParameter);
			method.Statements.Add(codeResult);
		}

		/// <summary>
		/// 生成 ExecuteScalar 方法调用
		/// </summary>
		/// <param name="members">方法集合</param>
		protected virtual void GenerateDesignerExecuteScalar(CodeTypeMemberCollection members) { }
		#endregion

		#region 生成 SearchEntity 方法
		protected internal void GenerateContextSearchEntity(CodeTypeMemberCollection members, CodeMemberMethod method)
		{
			string paramComment = string.Format("<param name=\"entity\">表示 {0} 类的实例。</param>", _EntityElement.EntityName);
			string returnComment = string.Format("<returns>如果查询结果存在则返回true，否则返回false。</returns>");
			method.Comments.Add(new CodeCommentStatement(paramComment, true));
			method.Comments.Add(new CodeCommentStatement(returnComment, true));
			method.Parameters.Add(new CodeParameterDeclarationExpression(_EntityElement.EntityName, "entity"));
			CodeVariableReferenceExpression entityReference = new CodeVariableReferenceExpression("entity");
			CodeVariableReferenceExpression accessReference = new CodeVariableReferenceExpression("access");
			CodeMethodReferenceExpression methodReference = new CodeMethodReferenceExpression(accessReference, MethodName);
			CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(methodReference);
			methodInvoke.Parameters.Add(entityReference);
			CodeMethodReturnStatement codeResult = new CodeMethodReturnStatement(methodInvoke);
			method.ReturnType = new CodeTypeReference(typeof(bool), CodeTypeReferenceOptions.GenericTypeParameter);
			method.Statements.Add(codeResult);
		}

		protected internal void GenerateDesignerSearchEntity(CodeTypeMemberCollection members)
		{
			CodeMemberMethod method = new CodeMemberMethod(); members.Add(method);
			this.CreateDesignerMemberMethod(method);
			string paramComment = string.Format("<param name=\"entity\">表示 {0} 类的实例。</param>", _EntityElement.EntityName);
			string returnComment = string.Format("<returns>如果查询结果存在则返回true，否则返回false。</returns>");
			method.Comments.Add(new CodeCommentStatement(paramComment, true));
			method.Comments.Add(new CodeCommentStatement(returnComment, true));
			CodeMethodReferenceExpression methodReference = new CodeMethodReferenceExpression();
			methodReference.MethodName = "SearchEntity";
			methodReference.TargetObject = new CodeBaseReferenceExpression();
			CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(methodReference);
			methodInvoke.Parameters.Add(new CodePrimitiveExpression(this.ConfigurationName));
			if (this.Parameters.Count > 0)
			{
				method.Parameters.Add(new CodeParameterDeclarationExpression(_EntityElement.EntityName, "entity"));
				method.Comments.Add(new CodeCommentStatement(paramComment, true));
				methodInvoke.Parameters.Add(new CodeVariableReferenceExpression("entity"));
			}
			CodeMethodReturnStatement codeResult = new CodeMethodReturnStatement(methodInvoke);
			method.ReturnType = new CodeTypeReference(typeof(bool), CodeTypeReferenceOptions.GenericTypeParameter);
			method.Statements.Add(codeResult);
		}
		#endregion

		/// <summary>
		/// 扩展设计时代码
		/// </summary>
		/// <param name="members">命令集合</param>
		/// <param name="method">当前命令DomCode</param>
		protected abstract void WriteContextDesignerCode(CodeTypeMemberCollection members, CodeMemberMethod method);

		/// <summary>
		/// 实现设计时代码
		/// </summary>
		/// <param name="members">当前命令使用的实体类信息</param>
		/// <param name="persistent">表示需要写入代码的类空间</param>
		/// <param name="provider">代码生成器和代码编译器的实例(一般为CSharpCodeProvider或VBCodeProvider)。</param>
		protected internal CodeMemberMethod WriteContextDesignerCode(CodeTypeMemberCollection members,
			PersistentConfiguration persistent, CodeDomProvider provider)
		{
			CodeMemberMethod method = new CodeMemberMethod
			{
				Name = MethodName,
				Attributes = MemberAttributes.Public | MemberAttributes.Final,
			};
			method.Comments.Add(new CodeCommentStatement("<summary>", true));
			method.Comments.Add(new CodeCommentStatement(_Comment, true));
			method.Comments.Add(new CodeCommentStatement("</summary>", true));
			string accessName = persistent.AccessName;
			CodeSnippetStatement usingStatement = new CodeSnippetStatement();
			string fileExtension = provider.FileExtension.ToLower();

			if (fileExtension == CShartFileExtension && _Persistent.ApplyConnection == false)
				usingStatement.Value = string.Concat("\t\t\tusing(", accessName, " access = new ", accessName, "())");
			else if (fileExtension == CShartFileExtension && _Persistent.ApplyConnection == true)
				usingStatement.Value = string.Concat("\t\t\tusing(", accessName, " access = new ", accessName, "(Connection))");
			else if (fileExtension == VisualBasicFileExtension && _Persistent.ApplyConnection == false)
				usingStatement.Value = string.Concat("\t\t\tUsing access As New ", accessName, "()");
			else if (fileExtension == VisualBasicFileExtension && _Persistent.ApplyConnection == true)
				usingStatement.Value = string.Concat("\t\t\tUsing access As New ", accessName, "(Connection)");
			method.Statements.Add(usingStatement);
			if (fileExtension == CShartFileExtension)
				method.Statements.Add(new CodeSnippetStatement("\t\t\t{"));
			WriteContextDesignerCode(members, method);
			if (fileExtension == CShartFileExtension)
				method.Statements.Add(new CodeSnippetStatement("\t\t\t}"));
			else if (fileExtension == VisualBasicFileExtension)
				method.Statements.Add(new CodeSnippetStatement("\t\t\tEnd Using"));
			members.Add(method);
			return method;
		}

		/// <summary>
		/// 在文件代码模型的类代码中查找指定的方法。
		/// </summary>
		/// <param name="codeClass">类的代码模型</param>
		/// <param name="functionName">方法名称</param>
		/// <returns>如果存在指定的方法则返回方法元素，否则返回空。</returns>
		private CodeFunction FindContextFunction(CodeClass codeClass, string functionName)
		{
			foreach (CodeElement element in codeClass.Members)
			{
				if (element.Kind == vsCMElement.vsCMElementFunction && element.Name == functionName)
				{
					return element as CodeFunction;
				}
			}
			return null;
		}

		/// <summary>
		/// 在指定的数据上下文类中添加当前命令的调用的方法，
		/// 如果存在则返回已存在的CodeFunction实例，否则创建当前方法关联的实例。
		/// </summary>
		/// <param name="codeClass">包含此方法的类信息</param>
		/// <param name="provider">代码自动生成提供器（含代码生成规则）</param>
		/// <returns>返回</returns>
		protected internal virtual EditPoint WriteContextCode(EnvDTE80.CodeClass2 codeClass, CodeDomProvider provider,
			DataEntityElement entity, PersistentConfiguration persistent)
		{
			CodeFunction function = FindContextFunction(codeClass, MethodName);
			if (function == null)
			{
				bool auto = _AutoGenerated;
				if (!_AutoGenerated) { _AutoGenerated = true; }
				CodeTypeMemberCollection members = new CodeTypeMemberCollection();
				CodeMemberMethod codeMethod = WriteContextDesignerCode(members, persistent, provider);
				if (!auto) { _AutoGenerated = auto; }
				CodeGeneratorOptions options = new CodeGeneratorOptions();
				options.BlankLinesBetweenMembers = true;
				options.BracingStyle = "C";// "C";
				System.Text.StringBuilder textBuilder = new System.Text.StringBuilder(1500);
				using (StringWriter writer = new StringWriter(textBuilder))
				{
					provider.GenerateCodeFromMember(codeMethod, writer, options);
				}
				function = codeClass.AddFunction(MethodName, vsCMFunction.vsCMFunctionFunction, vsCMTypeRef.vsCMTypeRefVoid, -1);
				//function = codeClass.AddFunction(MethodName, vsCMFunction.vsCMFunctionFunction, Type.Missing);
				EditPoint editPoint = function.StartPoint.CreateEditPoint();
				EditPoint movePoint = function.EndPoint.CreateEditPoint();
				editPoint.StartOfLine();
				movePoint.EndOfLine();
				editPoint.ReplaceText(movePoint, textBuilder.ToString(), (int)vsEPReplaceTextOptions.vsEPReplaceTextAutoformat);
				return editPoint;
			}
			return function.GetStartPoint(vsCMPart.vsCMPartBody).CreateEditPoint();
		}

		/// <summary>
		/// 创建 DataCommand 方法实体。
		/// </summary>
		/// <param name="method"></param>
		/// <param name="isAsync">当前方法是否是异步执行方法</param>
		protected internal void CreateDesignerMemberMethod(CodeMemberMethod method, bool isAsync = false)
		{
			method.Comments.Add(new CodeCommentStatement("<summary>", true));
			if (string.IsNullOrWhiteSpace(_Comment))
				method.Comments.Add(new CodeCommentStatement(string.Concat("调用 ", Name, " 命令"), true));
			else
				method.Comments.Add(new CodeCommentStatement(_Comment, true));
			method.Comments.Add(new CodeCommentStatement("</summary>", true));
			if (_MethodModifier == MethodModifierEnum.Public)
				method.Attributes = MemberAttributes.Public | MemberAttributes.Final;
			else if (_MethodModifier == MethodModifierEnum.Internal)
				method.Attributes = MemberAttributes.Assembly | MemberAttributes.Final;
			else if (_MethodModifier == MethodModifierEnum.Protected)
				method.Attributes = MemberAttributes.Family | MemberAttributes.Final;
			else if (_MethodModifier == MethodModifierEnum.ProtectedInternal)
				method.Attributes = MemberAttributes.FamilyAndAssembly | MemberAttributes.Final;
			method.Name = isAsync == true ? string.Concat(MethodName, "Async") : MethodName;
		}

		/// <summary>
		/// 实现设计时代码
		/// </summary>
		/// <param name="entity">当前命令使用的实体类信息</param>
		/// <param name="classCode">表示需要写入代码的类空间</param>
		/// <param name="targetFramework">生成代码的目标框架版本（例如：262144=v4.0）</param>
		protected internal abstract void WriteDesignerCode(CodeTypeDeclaration classCode, int targetFramework);
	}
}
